local random = math.random
--组合
function getCombination(tb,n)
    -- 从长度为m的数组中选n个元素的组合 https://www.cnblogs.com/ksir16/p/8041457.html
    local len = #tb
    if n > len then
        return {}
    end    
    local meta = {}
    -- init meta data
    for i=1, len do
        if i <= n then
            table.insert(meta, 1)
        else
            table.insert(meta, 0)
        end
    end
    local result = {}
    -- 记录一次组合
    local tmp = {}
    for i=1, len do
        if meta[i] == 1 then
            table.insert(tmp, tb[i])
        end
    end
    table.insert(result, tmp)
    while true do
        -- 前面连续的0
        local zero_count = 0
        for i=1, len-n do
            if meta[i] == 0 then
                zero_count = zero_count + 1
            else
                break
            end
        end
        -- 前m-n位都是0，说明处理结束
        if zero_count == len-n then
            break
        end
        local idx
        for j=1, len-1 do
            -- 10 交换为 01
            if meta[j]==1 and meta[j+1] == 0 then
                meta[j], meta[j+1] = meta[j+1], meta[j]
                idx = j
                break
            end
        end
        -- 将idx左边所有的1移到最左边
        local k = idx-1
        local count = 0
        while count <= k do
            for i=k, 2, -1 do
                if meta[i] == 1 then
                    meta[i], meta[i-1] = meta[i-1], meta[i]
                end
            end
            count = count + 1
        end
        -- 记录一次组合
        local tmp = {}
        for i=1, len do
            if meta[i] == 1 then
                table.insert(tmp, tb[i])
            end
        end
        table.insert(result, tmp)
    end
    return result
end
-- 浅拷贝
table.clone = function(t, nometa)
    local result = {}
    if not nometa then
        setmetatable(result, getmetatable(t))
    end
    for k, v in pairs (t) do
        result[k] = v
    end
    return result
end

-- 深拷贝
table.copy = function(t, nometa)
    local result = {}

    if not nometa then
        setmetatable(result, getmetatable(t))
    end

    for k, v in pairs(t) do
        if type(v) == "table" then
            result[k] = table.copy(v)
        else
            result[k] = v
        end
    end
    return result
end

--取子数组
table.sub = function(arr,star,n)
    local len = #arr
    if not n then 
    	n = len
    end

    if len < n or len < star then 
        return {}
    end
    local tb = {}
    for i = star, n do
        table.insert(tb,arr[i])
    end    
    return tb
end


table.removeSub = function(tb,tbSub)
    if not tbSub or not next(tbSub) then 
        return
    end
    local tbRemove = {}
    local tb2 = table.copy(tb)
    for k,v in pairs(tb2) do 
        for _,card in pairs(tbSub) do 
            if v == card then 
                table.insert(tbRemove,k)
            end
        end
    end
    local function sort(a,b)
        return a>b
    end 
    table.sort(tbRemove,sort)
    for k,v in pairs(tbRemove) do 
        table.remove(tb2,v)
    end    
    return tb2
end

--取剩余的数据
table.subRest = function(arr,star,n)
    local len = #arr
    if not n then 
        n = len
    end
    local tb = {}
    for i=1, star-1 do
        table.insert(tb,arr[i])
    end
    for i=star+n,len do 
        table.insert(tb,arr[i])    
    end
    return tb
end

--连接 
table.concatList = function (tb1,tb2)
	if type(tb1)~='table' or type(tb2) ~='table' then 
		return
	end
    for _,v in pairs(tb2) do 
        table.insert(tb1,v)
    end
end

--打乱数组
table.mix = function(arr)
    local sz = #arr
    for i = 1 , sz do
        local r = random(i, sz)
        local t = arr[i]
        arr[i] = arr[r]
        arr[r] = t
    end
end

function class(classname, super)
	local superType = type(super)
	local cls
	if superType ~= 'function' and superType ~= 'table' then
		superType = nil
		super = nil
	end

	if superType == 'function' or (super and super.__ctype == 1) then
		-- inherited from native C++ Object
		cls = {}
		if superType == 'table' then
			-- copy fields from super
			for k,v in pairs(super) do cls[k] = v end
			cls.__create = super.__create
			cls.super = super
		else
			cls.__create = super
			cls.ctor = function() end
		end
		cls.__cname = classname
		cls.__ctype = 1

		function cls.new(...)
			local instance = cls.__create(...)
			-- copy fields from class to  native object
			for k, v in pairs(cls) do instance[k] = v end
			instance.class = cls
			instance:ctor(...)
			return instance
		end
                cls.New = cls.new
	else
		-- inherited from Lua Object
		if super then
			cls = {}
			setmetatable(cls, {__index = super})
			cls.super = super
		else
			cls = {ctor = function() end}
		end
		cls.__cname = classname
		cls.__ctype = 2 --lua
		cls.__index = cls

		function cls.new(...)
			local instance = setmetatable({}, cls)
			instance.class = cls
			instance:ctor(...)
			return instance
		end
                cls.New = cls.new
	end
	return cls
end


---不会死循环的dump
local function dump(tab, _tostring)
    _tostring = _tostring and _tostring or tostring

    local function getkey(k, ktype)
        if ktype == 'number' then
            return '[' .. k .. ']'
        elseif ktype == 'string' then
            return '["' .. k .. '"]'
        else
            return '[' .. _tostring(k) .. ']'  --key可能是table
        end
    end

    local tinsert = table.insert
    local mmax = math.max
    local rep = string.rep
    local gsub = string.gsub
    local format = string.format

    local function dump_obj(obj, key, sp, lv, st)
        local sp = '\t'

        if type(obj) ~= 'table' then
            return sp .. (key or '') .. ' = ' .. tostring(obj) .. '\n'
        end

        local ks, vs, s= { mxl = 0 }, {}
        lv, st =  lv or 1, st or {}

        st[obj] = key or '.' --table对象列表
        key = key or ''
        for k, v in pairs(obj) do
            local ktype, vtype = type(k), type(v)
            if k ~= 'class' and k ~= '__index' and vtype ~= 'function'then
                if vtype == 'table' then
                    if st[v] then --相互引用的table，直接输出
                        vs[#vs + 1] = '[' .. st[v] .. ']'
                        s = sp:rep(lv) .. getkey(k, ktype)
                        tinsert(ks, s)
                        ks.mxl = mmax(#s, ks.mxl)
                    else
                        st[v] = key .. '.' .. _tostring(k) --保存dump过的table，key可能也是table
                        vs[#vs + 1] = dump_obj(v, st[v], sp, lv + 1, st)
                        s = sp:rep(lv) .. getkey(k, ktype)
                        tinsert(ks, s)
                        ks.mxl = mmax(#s, ks.mxl)
                    end
                else
                    if vtype == 'string' then
                        vs[#vs + 1] = (('%q'):format(v):gsub('\\\10','\\n'):gsub('\\r\\n', '\\n'))
                    else
                        vs[#vs + 1] = tostring(v)
                    end
                    s = sp:rep(lv) .. getkey(k, ktype)
                    tinsert(ks, s)
                    ks.mxl = mmax(#s, ks.mxl);
                end
            end
        end

        s = ks.mxl
        for i, v in ipairs(ks) do
            vs[i] = v .. (' '):rep(s - #v) .. ' = ' .. vs[i] .. '\n'
        end

        return '{\n' .. table.concat(vs) .. sp:rep(lv-1) .. '}'
    end

    return dump_obj(tab)
end

----------------------------------
----------------------------------
----------------------------------
----------------------------------
----------------------------------


local random = math.random
local floor = math.floor
local Rule = class("Rule")
local tbl_huxi = require "TblHuxi"
local tbl_split = require "TblSplit"

function  Rule:ctor()
	--随机种子
	math.randomseed(os.time())
	--40张原牌
	self.card = {
		
	}	
	--要发的牌
	self.tbCard = {}
	--牌色
	self.colorType = {
		black=1,
		red=2,
	}
	--牌型
	self.cardType={
		danZhang=1, --单张
		duiZi=2,--一对
		kan=3,--一坎
		ti=4,--一提
		shun=5,--顺子
		jiao=6,-- 绞牌			
	}
	-- 默认可以胡牌的胡息
	self.minHuxi = 15	
end

--洗牌
function Rule:shuffle(cardNum)	
	--小张		
	for i=1,10 do
		for k=1,4 do
			table.insert(self.card,0x10+i)			
		end
	end
	--大张
	for i=1,10 do
		for k=1,4 do
			table.insert(self.card,0x20+i)			
		end
	end	
	for _, v in pairs(self.card) do 
		table.insert(self.tbCard, v)
	end	
	--搞乱顺序
	table.mix(self.tbCard)

end

--取指定个数的牌
function Rule:getCard(num)
	local tbRes = {}
	local n = num or 0
	for k,v in pairs(self.tbCard) do 
		if n <= 0 then break end
		if v then 
			n = n-1
			table.insert(tbRes,v)
			self.tbCard[k] = nil
		end
	end
	return tbRes
end

--取牌值
function Rule:getCardNum(card)
	return card & 0x0f
end

--取牌色
function Rule:getCardColor(card)
	local num = card & 0x0f
	if num == 2 or num == 7 or num == 10 then 
		return self.colorType.red 
	end
	return self.colorType.black
end

--取牌类型
function Rule:getCardType(card)	
	return card & 0xf0
end

function Rule:has(tb,value)
	for i,v in ipairs(tb) do
		if v == value then
			return true
		end
	end
	return false
end

--打印16进制牌
function Rule:printCard(card)
	local str = string.format("0x%x",card)
	print(str)
end

--对牌排序
function Rule:sortCards(tbCard)
	local n1,n2
	local c1,c2
	local function sortFun(a,b)
		n1 = self:getCardNum(a)
		n2 = self:getCardNum(b)
		c1 = self:getCardType(a)
		c2 = self:getCardType(b)		
		if c1 > c2 then 
			return true
		elseif c1 == c2 then 
			if n1 < n2 then 
				return true
			end
		end
		return false
	end
	table.sort(tbCard,sortFun)	
end

--绞牌
function Rule:isJiao(cards)
	if #cards == 3 then
		self:sortCards(cards)
		local num1 = self:getCardNum(cards[1])
		local num2 = self:getCardNum(cards[2])
		local num3 = self:getCardNum(cards[3])
		if self:getCardType(cards[1]) ~= self:getCardType(cards[3]) then
			if num1==num2 and num2==num3 then 
				return true
			end
		end
	end
	return false
end

--一对
function Rule:isDuizi(cards)
	if #cards == 2 then 
		if cards[1] == cards[2] then 
			return true
		end
	end
	return false
end

--一句话
function Rule:isShun(cards)
	if #cards == 3 then
		self:sortCards(cards)
		if cards[1] + 1 == cards[2] and cards[1] + 2 == cards[3] then
			return true
		end
		--2,7,10
		if self:getCardNum(cards[1]) == 2 and cards[1] + 5 == cards[2] 
			and cards[1] + 8 == cards[3] then
			return true
		end
	end
	return false
end

--一坎牌
function Rule:isShun(cards)
	if #cards == 3 then
		self:sortCards(cards)
		if cards[1] == cards[2] and cards[1] == cards[3] then
			return true
		end
	end
	return false
end

--一堤牌
function Rule:isTi(cards)
	if #cards == 4 then
		self:sortCards(cards)
		if cards[1] == cards[4] then
			return true
		end
	end
end

--一手牌中各个牌的个数
function Rule:getAllValueNums(cards)
	local ret = {}
	for _,v in pairs(cards) do
		if ret[v] then
			ret[v] = ret[v] + 1
		else
			ret[v] = 1
		end
	end
	return ret
end
function Rule:get_all_value_nums(cards)
	local ret = {}
	for _,v in pairs(cards) do
		if ret[v] then
			ret[v] = ret[v] + 1
		else
			ret[v] = 1
		end
	end
	return ret
end

--大牌对应的小牌， 小牌对应的大牌
function Rule:getOtherTypeCard(card)
	local cardType = self:getCardType(card)
	if cardType == 0x10 then 
		return card + 0x10 
	elseif cardType == 0x20 then 
		return card - 0x10
	end
	return nil
end

--能否碰
function Rule:checkPeng(cards,card)
	local cardNums = self:getAllValueNums(cards)
	if cardNums[card] == 2 then
		return true
	end
	return false
end

--能否吃
function Rule:checkChi(set,single)
	local _type  = self:getCardType(single)
	local _value = self:getCardNum(single)
	local card_nums = self:getAllValueNums(set)
	--组成顺
	local set_t = {}
	if single <= 0x20 then
		for i=0x10 + 1, 0x10 + 10 do
			set_t[i] = card_nums[i]
		end
	else
		for i=0x20 + 1, 0x20 + 10 do
			set_t[i] = card_nums[i]
		end
	end
	--不要获取比的情况	
	local chi_data = {}
	local set_t = table.copy(set)
	self:add(set_t,single)
	local all_chi = self:getAllJiaoShun(single,set_t)
	for k,v in pairs(all_chi) do
		local set_tt = table.copy(set_t)
		for i=1,#v do
			self:drop(set_tt,v[i])
		end
		local all_comp = self:getCompare(single,set_tt)
		if not all_comp then
			table.insert(chi_data,{cards = v ,comp = all_comp})
		else
			for i=1,#all_comp do
				table.insert(chi_data,{cards = v ,comp = all_comp[i]})
			end
		end
	end
	print("_____all_chi_",dump(all_chi))
	if #chi_data > 0 then
		print("___chi_data",dump(chi_data))
		return true,chi_data
	else
		return false
	end
	
end

--获取所有的绞和顺 返回所有的绞和顺并返回除这些牌以外的新牌组
function Rule:getAllJiaoShun(card,set)
	local set_t = table.copy(set)
	-- local card_nums = self:getAllValueNums(set_t)
	local jiao = self:getAllJiao(card,set_t)
	local shun = self:getAllShun(card,set_t)

	return self:mergeTable(jiao,shun)
end

function Rule:mergeTable(t1,t2)
	local ret = {}
	for k,v in pairs(t1) do
		table.insert(ret,v)
	end
	for k,v in pairs(t2) do
		table.insert(ret,v)
	end
	return ret
end

function Rule:drop(t,c)
	for i,v in ipairs(t) do
		if v == c then
			table.remove(t,i)
			return true
		end
	end
end

function Rule:add(t,c)
	if type(c) == "table" then
		for _,v in ipairs(c) do
			table.insert(t,v)
		end
	else
		table.insert(t,c)
	end
end

function Rule:getAllJiao(card,cards)
	local tempCards = table.copy(cards)
	local card_nums = self:getAllValueNums(tempCards)
	local jiao = {}
	if not card then
		for i=1,10 do
			if card_nums[0x10|i] and card_nums[0x20|i] then
				if card_nums[0x10|i]==1 and card_nums[0x20|i]==2 then
					table.insert(jiao,{0x10|i,0x20|i,0x20|i })

				elseif card_nums[0x10|i]==2 and card_nums[0x20|i]==1 then
					table.insert(jiao,{0x10|i,0x10|i,0x20|i})

				elseif card_nums[0x10|i]==2 and card_nums[0x20|i]==2 then
					table.insert(jiao,{0x10|i,0x10|i,0x20|i})
					table.insert(jiao,{0x10|i,0x20|i,0x20|i})
				end
			end
		end
	else
		local other = self:getOtherTypeCard(card)
		if card_nums[card] and card_nums[other] then
			if card_nums[card]==1 and card_nums[other]==2 then
				table.insert(jiao,{card, other, other})

			elseif card_nums[card]==2 and card_nums[other]==1 then
				table.insert(jiao,{card,card,other})

			elseif card_nums[card]==2 and card_nums[other]==2 then
				table.insert(jiao,{card,card,other})
				table.insert(jiao,{card,other,other})
			end
		end
	end
	return jiao
end

function Rule:getAllShun(card,cards)
	local _type  = self:getCardType(card)
	local _value = self:getCardNum(card)
	local tempCards  = table.copy(cards)
	local card_nums = self:getAllValueNums(tempCards)
	local shun = {}
	if card then
		if card_nums[card-2] and card_nums[card-1] and card_nums[card] then
			table.insert(shun,{card-2,card-1,card})
		end
		if card_nums[card-1] and card_nums[card] and card_nums[card+1] then
			table.insert(shun,{card-1,card ,card+1})
		end
		if card_nums[card] and card_nums[card+1] and card_nums[card+2] then
			table.insert(shun,{card,card+1,card+2})
		end

		if _value==2 or _value==7 or _value==10 then
			local cardNum = _type
			if self:has(tempCards,(cardNum+2)) and
				self:has(tempCards,(cardNum+7)) and
				self:has(tempCards,(cardNum+10)) then
				table.insert(shun,{cardNum+2,cardNum+7,cardNum+10})								
			end
		end
	else
		for k,v in pairs(card_nums) do
			if card_nums[k+1] and card_nums[k+2] then
				table.insert(shun,{k,k + 1,k + 2})
			end
			if self:getCardNum(k)==2 then
				if card_nums[k+5] and card_nums[k+8] then
					table.insert(shun,{k,k + 5,k + 8})
				end
			end
		end
	end
	return shun
end

--取比
function Rule:getCompare(card,cards)
	if not self:has(cards,card) then
		return
	end
	local comp = {}
	local all_cards = self:getAllJiaoShun(card,cards)
	for k,v in pairs(all_cards) do
		local set_t = table.copy(cards)
		for i=1,#v do
			self:drop(set_t,v[i])
		end
		if self:has(set_t,card) then
			local all_cards2 = self:getAllJiaoShun(card,set_t)
			if #all_cards2 > 0 then
				for x,y in pairs(all_cards2) do
					table.insert(comp,{{cards=v},{cards=y}})
				end
			else
				print("============")
			end
		else
			table.insert(comp,{{cards=v}})
		end
	end
	return comp
end

--能否偎牌
function Rule:checkWei(cards,card)
	local cardNums = self:getAllValueNums(cards)
	if cardNums[card] and cardNums[card] == 2 then 
		return true
	end
	return false
end

--能否偍牌
function Rule:checkTi(cards,card)
	local cardNums = self:getAllValueNums(cards)
	if cardNums[card] and cardNums[card] == 3 then 
		return true
	end
	return false
end




--把手牌转为个数表
function Rule:getCardNumTable(cards)
	local tcards = {
		0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0
	}	
	local card
	local tp 
	for k,v in pairs(cards) do 
		tp = self:getCardType(v)
		card = self:getCardNum(v)
		if tp==0x20 then 
			tcards[card+10]=tcards[card+10]+1
		else
			tcards[card]=tcards[card]+1
		end
	end
	return tcards
end

-- 获取特定类型，特定牌胡息
function Rule:get_group_huxi(t,cards)
	local card = cards[1]
	if t == "peng" then		-- 碰
		if card <= 10 then
			return 1
		else
			return 3
		end
	elseif t == "wei" then	-- 偎
		if card <= 10 then
			return 3
		else
			return 6
		end
	elseif t == "pao" then	-- 跑
		if card <= 10 then
			return 6
		else
			return 9
		end
	elseif t == "ti" then	-- 提
		if card <= 10 then
			return 9
		else
			return 12
		end
	elseif t== "chi" then 
		--顺子123,27a
		self:sortCards(cards)
		if (cards[1]==1 and cards[2]==2 and cards[3]==3) or
			(cards[1]==2 and cards[2]==7 and cards[3]==10) then
			return 3 
		elseif (cards[1]==11 and cards[2]==12 and cards[3]==13) or
				(cards[1]==12 and cards[2]==17 and cards[3]==20)	then
			return 6 	
		end
	end
	return 0
end

-- 获取坎外手牌、坎牌胡息、桌面牌胡息
function Rule:get_huxi_pre(cards,groups)
	local tcards = {
		0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0
	}
	local menZi = #groups
	local kan_huxi = 0
	-- 计算牌张数、坎的胡息
	for i,v in pairs(cards) do
		if v == 3 then
			kan_huxi = kan_huxi + self:get_group_huxi("wei",{i})
			print("____坎__",i,i,i)
			menZi = menZi + 1
		else
			tcards[i] = v
		end
	end

	local tipao = false
	local groups_huxi = 0
	-- 获取桌上吃、碰、偎、跑、提的总胡息
	for _,group in ipairs(groups) do
		groups_huxi = groups_huxi + self:get_group_huxi(group.t,group.cards)
		if group.t == "pao" or group.t == "ti" then
			tipao = true
		end
	end
	return tcards,kan_huxi,groups_huxi,tipao,menZi
end

-- 获取所有能听的牌
function Rule:get_ting_cards(cards,curhuxi,menziNum)
	print("____ting___",cards,curhuxi,menziNum)
	local tbRes = {}
	local bHu,huxi,tbMen
	for card=0x11,0x1a do
		bHu,huxi,tbMen = self:checkHu(cards,card,curhuxi,menziNum)
		if bHu then 
			table.insert(tbRes,{bHu,huxi,card})
		end
	end
	for card=0x21,0x2a do
		bHu,huxi,tbMen = self:checkHu(cards,card,curhuxi,menziNum)
		if bHu then 
			table.insert(tbRes,{bHu,huxi,card})
		end
	end	
	return tbRes
end

-- 若能胡，返回胡息，若不能胡，返回-1
-- cards 表示手牌
-- groups 表示吃、碰、跑、提的牌
-- c表示自己摸到的牌
function Rule:get_huxi_self(cards,groups,c)
	local tcards,kan_huxi,groups_huxi,tipao,menZi = self:get_huxi_pre(cards,groups)

	-- 提胡
	if not tipao and cards[c] == 3 then
		local add_huxi = self:get_group_huxi("ti",{c}) - self:get_group_huxi("wei",{c})
		return self:get_huinfo(tcards,kan_huxi+groups_huxi+add_huxi,menZi)
	end

	-- 跑胡、破跑胡
	for _,group in pairs(groups) do
		if (group.t == "peng" or group.t == "wei") and group.card == c then
			-- 跑胡
			if not tipao then
				local add_huxi = self:get_group_huxi("pao",{c})-self:get_group_huxi(group.t,{c})
				local r = self:get_huinfo(tcards,kan_huxi+groups_huxi+add_huxi,menZi)
				if r > 0 then
					return r
				end
			end
			-- 破跑胡
			tcards[c] = 1
			return self:get_huinfo(tcards,kan_huxi+groups_huxi,menZi)
		end
	end

	-- 偎胡
	if cards[c] == 2 then
		tcards[c] = 0
		local add_huxi = self:get_group_huxi("wei",{c})
		return self:get_huinfo(tcards,kan_huxi+groups_huxi+add_huxi,menZi)
	end

	-- 吃胡
	tcards[c] = tcards[c] + 1
	print("_111111___c__",c)
	return self:get_huinfo(tcards,kan_huxi+groups_huxi,menZi)
end

-- 判断剩余的手牌是否能胡
function Rule:get_huinfo(cards,huxi,menZi)
	local need_huxi = self.minHuxi - huxi	
	local need_menzi = 7-menZi
	local sum = 0
	local tbShun = {}
	local tbMenZi = {}	
	local tbRes = {}
	local maxHuxi = huxi --最大胡息
	for _,n in ipairs(cards) do
		sum = sum + n
	end
	if sum == 0 then
		--
		print("___11111111____没有手牌了____")
		if need_huxi<=0 and need_menzi==0 then
			return true,maxHuxi,tbRes
		end
		return false,maxHuxi,tbRes
	end
	-- 不需要将的情况
	local need_eye = (sum % 3 == 2)
	-- print(dump(cards))
	print("____need_eye__",need_eye,need_huxi)
	for k,v in ipairs(tbl_huxi) do
		local check = true
		maxHuxi = huxi
		for card,num in pairs(v) do
			if type(card)=="number" and cards[card] < num then
				check = false
				break
			end
		end
		if check then
			--有123或2710 
			-- 扣除相应牌
			for card,num in pairs(v) do
				if type(card) == "number" then
					cards[card] = cards[card] - num
					tbShun = self:splitToMenZi(v)
				end	
			end
			
			local menzi = need_menzi-#tbShun
			local canhu = self:can_hu(cards,1,need_eye,tbMenZi,menzi)
			-- print("____2710__",dump(cards),canhu)
			-- 加回相应牌
			for card,num in pairs(v) do
				if type(card) == "number" then
					cards[card] = cards[card] + num
				end
			end			
			if canhu then
				if next(tbShun) then 
					print("__123，2710__",dump(tbShun))
				end
				print("_散门子__",dump(tbMenZi))	
				for _,m in pairs(tbShun) do 
					table.insert(tbRes,m)
				end
				for _,tbm in pairs(tbMenZi) do
					for _,m in pairs(tbm) do 
						table.insert(tbRes,m)
					end
				end
				maxHuxi = maxHuxi + v.huxi
				print("______maxHuxi__",maxHuxi,k,v.huxi)
				if self.minHuxi > maxHuxi then
					return false,maxHuxi,tbRes
				end				
				return true,maxHuxi,tbRes
			else
				print("__v.huxi____",v.huxi)
				-- maxHuxi = maxHuxi + v.huxi
			end
		end
	end
	if need_huxi > 0 then
		return false,huxi,tbRes
	end
	--没有123，2710 的情况
	if self:can_hu(cards,1,need_eye,tbMenZi,need_menzi) then
		for _,tbm in pairs(tbMenZi) do
			for _,m in pairs(tbm) do 
				table.insert(tbRes,m)
			end
		end		
		print("_222散门子__",dump(tbMenZi))
		return true,maxHuxi,tbRes
	end
	return false,maxHuxi,tbRes
end


-- 尝试各种拆分方式，只要有一种能胡，则能胡
function Rule:can_hu(cards,i,need_eye,tbMenZi,menZi)
	print("_______menZi__",dump(cards),i,need_eye,dump(tbMenZi),menZi)
	if i > 10 then
		print("_______>10",i)
		return true
	end
	while cards[i] + cards[i+10] == 0 do
		if i == 10 then
			print("_______=10")
			if menZi == 0 then 
				return true
			else
				return false
			end
		end
		i = i + 1
	end

	for sk,split in ipairs(tbl_split) do
		if (not split.eye or need_eye) and split[0]==cards[i] and split[10]==cards[i+10] then
			local can = true
			if (split[2] and (i+2>10 or cards[i+2]<split[2])) or (split[1] and (i+1>10 or cards[i+1]<split[1])) then
				can = false
			end
			
			if (split[12] and (i+12>20 or cards[i+12]<split[12])) or (split[11] and (i+11>20 or cards[i+11]<split[11])) then
				can = false
			end

			if can then
				-- print(dump(split))
				print("____i____",i,sk,cards[i],cards[i+10])
				local tbCard = {}		
				local tbLessMenZi = {}
				-- 扣除相关牌
				for k,v in pairs(split) do
					if type(k)=="number" then
						cards[i+k] = cards[i+k] - v
						for a=1,v do 
							table.insert(tbCard,i+k)
						end		
					end
				end
				if next(tbCard) then 
					tbLessMenZi = self:getLessCardMenZi(sk,tbCard)
				end
				table.insert(tbMenZi,tbLessMenZi)	
				local sum = 0
				for _,n in ipairs(cards) do
					sum = sum + n
				end				
				local need_eye = (sum % 3 == 2)	
				local canhu = self:can_hu(cards,i+1,need_eye,tbMenZi,menZi-#tbLessMenZi)
				-- 加回相关牌
				for k,v in pairs(split) do
					if type(k)=="number" then
						cards[i+k] = cards[i+k] + v
					end
				end
				if canhu then
					-- print("tbMenZi____",dump(tbMenZi))	
					local num = 0
					for k,v in pairs(tbMenZi) do 
						num = num + #v
					end
					print("___num__",num,menZi)
					return true
				else
					table.remove(tbMenZi,#tbMenZi)
				end
			end
		end
	end

	return false
end

--拆成门子
function Rule:splitToMenZi(tb)
	local tbShun = {
		{1,2,3},
		{11,12,13},
		{2,7,10},
		{12,17,20},
	}
	local res = {}
	local has
	local tempList = table.copy(tb)
	for i=1,4 do 
		for _,v in pairs(tbShun) do 
			has = true
			for _,card in pairs(v) do 
				if not tempList[card] or tempList[card]==0 then 
					has = false
				end
			end
			if has then 
				for _,card in pairs(v) do 
					tempList[card] = tempList[card] -1
				end
				-- print(dump(v))
				table.insert(res,v)
			end
		end
	end
	return res
end

function Rule:getDui(tcards)
	local res = {}
	for k,v in pairs(tcards) do
		if v>=2 then
			table.insert(res, {k,k})
		end
	end
	return res
end
--取一个顺子
function Rule:getShun(tcards)
	local res = {}
	local a,b,c
	for k,v in pairs(tcards) do
		b = true
		while b do 
			a = tcards[k+1]
			c = tcards[k+2]
			if v>0 and a and c and a>0 and c>0 then
				tcards[k+1]=tcards[k+1]-1
				tcards[k+2]=tcards[k+2]-1
				tcards[k]=tcards[k]-1
				table.insert(res,{k,k+1,k+2})
			else
				b=false
			end
			if tcards[k]<=0 then 
				b=false
			end
		end
	end
	return res
end
function Rule:getJiao(tcards)
	local res = {}
	local a,b 
	for k,v in pairs(tcards) do		
		a = tcards[k]
		b = tcards[k+10]
		if a and b then 
			if a>=1 and b>= 2 then
				table.insert(res,{k,k+10,k+10})
			elseif a>=2 and b>= 1 then
				table.insert(res,{k,k,k+10})
			elseif a>=2 and b>=2 then
				table.insert(res,{k,k,k+10})
				table.insert(res,{k,k+10,k+10})
			end
		end
	end	
	return res
end
function Rule:getKan(tcards)
	local res = {}
	for k,v in pairs(tcards) do		
		if tcards[k]==3 and tcards[k+10] == 0 then
			table.insert(res,{k,k,k})
		elseif tcards[k]==0 and tcards[k+10] == 3 then
			table.insert(res,{k+10,k+10,k+10})
		end
	end	
	return res
end

function Rule:getLessCardMenZi(sk,tbCard)
	local tcards = {
		0,0,0,0,0,0,0,0,0,0,
		0,0,0,0,0,0,0,0,0,0
	}
	local res = {}

	for k,v in pairs(tbCard) do
		tcards[v] = tcards[v]+1
	end		
	local temp = table.copy(tcards)
	local tbShun = self:getShun(temp)
	temp = table.copy(tcards)
	print("____tcards__",dump(tcards))
	local tbJiao = self:getJiao(temp)
	temp = table.copy(tcards)
	local tbDui = self:getDui(temp)
	temp = table.copy(tcards)
	local tbKan = self:getKan(temp)
	print("shun",dump(tbShun))
	print("jiao",dump(tbJiao))
	-- print("dui",dump(tbDui))
	-- print("kan",dump(tbKan))
	-- if 1 then return end
	-- 1顺子 1-2
	if sk>=1 and sk<=2 then 
		return tbShun
	end
	-- 2顺子 3-5
	if sk>=3 and sk<=5 then 
		return tbShun
	end	
	-- 3顺子 6-7
	if sk>=6 and sk<=7 then 
		return tbShun
	end		
	-- 1绞 8-9
	if sk>=8 and sk<=9 then 
		return tbJiao
	end	
	-- 1绞一顺 10-11 12-13
	if sk>=10 and sk<=13 then 
		table.insert(res,tbJiao[1])
		table.insert(res,tbShun[1])
	end		
	-- 1将 14-15
	if sk>=14 and sk<=15 then 
		return tbDui
	end		
	-- 1将1顺 16-19
	if sk>=16 and sk<=19 then 
		table.insert(res,tbDui[1])
		table.insert(res,tbShun[1])
	end		
	-- 1将2顺 20-23 
	if sk>=20 and sk<=23 then 
		local temp = table.copy(tcards)		
		local ts = {}
		for k,v in pairs(temp) do 
			if v>=2 then 				
				temp[k]=temp[k]-2
				ts = self:getShun(temp)
				if #ts == 2 then 
					table.insert(res,{k,k})
					for i,j in pairs(ts) do 
						table.insert(res,j)
					end
					return res
				end		
				temp[k]=temp[k]+2		
			end
		end
	end		
	-- 1将3顺 24-25
	if sk>=24 and sk<=25 then 
		local temp = table.copy(tcards)		
		local ts = {}
		for k,v in pairs(temp) do 
			if v>=2 then 
				temp[k]=temp[k]-2
				ts = self:getShun(temp)
				if #ts == 3 then 
					table.insert(res,{k,k})
					for i,j in pairs(ts) do 
						table.insert(res,j)
					end
					return res
				end		
				temp[k]=temp[k]+2		
			end
		end
	end		
	-- 1将1绞 26-27
	if sk>=26 and sk<=27 then 
		local temp = table.copy(tcards)		
		local ts = {}
		for k,v in pairs(temp) do 
			if v==2 then 
				temp[k]=temp[k]-2
				ts = self:getJiao(temp)
				if #ts == 1 then 
					table.insert(res,{k,k})
					for i,j in pairs(ts) do 
						table.insert(res,j)
					end
					return res
				end		
				temp[k]=temp[k]+2		
			end
		end
	end		
	-- 1砍 28-29
	if sk>=26 and sk<=27 then
		return tbKan
	end	
	return res
end

--能否胡牌
function Rule:checkHu(cards,card,huxi,menziNum)
	--[[
		1.至少15胡息
		2.7方门子
	--]]
	print("___checkHu__",cards,card,huxi,menziNum)
	self:sortCards(cards)
	local cards = self:getCardNumTable(cards)
	if card then 
		local tp = self:getCardType(card)
		card = self:toOtherType(card)		
		cards[card] = cards[card] + 1
	end
	-- huxi = 15
	-- menziNum = 5
	local bHu, huxi,tbMen = self:get_huinfo(cards,huxi,menziNum)
	print("胡结果:",bHu,huxi,dump(tbMen))
	local tbMen = table.copy(tbMen) --防止出现重叠引用问题
	if bHu then 
		for _,v in pairs(tbMen) do 
			for k,c in pairs(v) do 
				if c <= 10 then 
					v[k] = 0x10+c
				else
					v[k] = 0x20+(c-10)
				end
			end
		end
	end
	-- print("门子",dump(tbMen))
	return bHu,huxi,tbMen

end

function Rule:toOtherType(card)
	local tp = self:getCardType(card)
	card = self:getCardNum(card)
	if tp==0x20 then 
		card = card + 10
	end	
	return card
end



local rule = Rule.new()

	local groups = {
		{t = "ti",cards = {9,9,9,9} }, -- 
		{t = "chi",cards = {1,2,3} } -- 
	}
local tbCard = 	{
		0x14,0x24,0x24,
		0x22,0x27,0x2a,
		0x28,0x28,0x28,
		0x15,0x16,0x17,
		0x12,
	}
rule:sortCards(tbCard)
-- for k,v in pairs(tbCard) do 
-- 	rule:printCard(v)
-- end

-- print(dump(rule:getAllJiao(0x11,tbCard)))
-- print(rule:checkWei(tbCard,0x12))
-- print(dump(rule:getCardNumTable(tbCard)))
-- local tb = rule:getAllValueNums(tbCard)
-- print(dump(tb))

-- rule:printCard(rule:getCardType(0x21))

-- local cards = rule:getCardNumTable(tbCard)
-- local huxi = rule:get_huxi_self(cards,groups,3)
-- print(huxi)
-- print(dump(cards))


local cards={
	0x21,0x22,0x23,
	0x15,0x16,0x17,
	0x12,0x17,0x1a,
	0x1a,0x2a,0x2a,
	0x15,0x25,
}
local huxi = 6
local menziNum = 2
local card = 0x15
rule:checkHu(cards,card,huxi,menziNum)
-- local res = rule:get_ting_cards(cards,huxi,menziNum)
-- print("_ting_结果___",dump(res))
	-- {[0]=2, [10]=2, [11]=2, [12]=2, eye=true}, 
	-- {[0]=3, [1]=1, [2]=1, [10]=1, [11]=1, [12]=1, eye=true}, 
	-- {[0]=2, [1]=2, [2]=2, [10]=2, eye=true}, 
	-- {[0]=1, [1]=1, [2]=1, [10]=3, [11]=1, [12]=1, eye=true},  
local cards = 	{
	0,0,0,1,1,1,0,0,0,0,
	0,0,0,3,1,1,0,0,0,0,	
}
local tbMenZi = {}
local need_eye = true
-- local canHu = rule:can_hu(cards,1,need_eye,tbMenZi)
-- print(canHu)
-- if canHu then 
-- 	print(dump(tbMenZi))

	-- print(dump(getLessCardMenZi(23,tbMenZi[1])))
-- end
local tb = {4,4,4,5,6,17,18,19,8,6,7}
-- print(dump(getCombination(tb,3)))
-- print(dump(rule:getLessCardMenZi(25,tb)))
local tb = {
	0x12,0x17,0x1a,
	0x12,0x17,0x1a,
	0x37,0x37,
	0x13,0x13,
}
-- rule:checkChi(tb,0x13)
-- rule:canHu(cards,1,true,{})
-- local res = rule:get_all_value_nums(tb)
-- local set = {}
-- local kan = {}
-- 	for k,v in pairs(res) do
-- 		if v == 3 then
-- 			rule:drop(set,k)
-- 			rule:drop(set,k)
-- 			rule:drop(set,k)
-- 			table.insert(kan,{k,k,k})
-- 		end
-- 	end
-- print(dump(kan))

-- 对数值进行四舍五入，如果不是数值则返回 0
-- @function [parent=#math] round
-- @param number value 输入值
-- @return number#number 

function math.round(value)
    value = tonumber(value) or 0
    return math.floor(value + 0.5)
end
